package com.nineshadow.games.core;

import cn.stylefeng.guns.modular.system.model.GameLog;
import cn.stylefeng.guns.modular.system.model.GameUser;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.nineshadow.games.Enum.GameStatusEnum;
import com.nineshadow.games.Enum.GameTypeEnum;
import com.nineshadow.games.core.step.Step1Start;
import com.nineshadow.games.core.step.Step2Over;
import com.nineshadow.games.interfaces.IStep;
import com.nineshadow.games.launch.GameWorld;
import com.nineshadow.games.launch.HallServer;
import com.nineshadow.games.util.MyUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class GameRoom implements Runnable {

    /**
     * 所有游戏运行步骤
     */
    private final Map<Class<? extends IStep>, IStep> stepMap;
    /**
     * 订阅标识
     */
    public String SubscribeTab;
    /**
     * 已加入房间的用户
     */
    public volatile List<GameUser> users = new ArrayList<>();
    /**
     * 游戏类型
     */
    protected GameTypeEnum gameTypeEnum;
    /**
     * 下一游戏运行步骤
     */
    protected volatile Class<? extends IStep> nextStepClass;
    /**
     * 当前游戏运行步骤
     */
    protected volatile Class<? extends IStep> currStepClass;
    /**
     * 游戏房间是否被终止
     */
    protected volatile boolean isTerminated;

    public GameRoom(GameTypeEnum gameTypeEnum, String SubscribeTab) {
        log.info("创建房间类型：{}----房间id：{}", gameTypeEnum.getMsg(), SubscribeTab);
        stepMap = Collections.unmodifiableMap(initStepMap());
        List<GameLog> gameLogs = HallServer.gameLogService.selectList(new EntityWrapper<GameLog>()
                .eq("room_id", Integer.valueOf(SubscribeTab)));
        for (GameLog gameLog : gameLogs) {
            GameUser gameUser = HallServer.gameUserService.selectById(gameLog.getUserId());
            users.add(gameUser);
        }
        //设置游戏记录为游戏中
        HallServer.gameLogService.updateRoomState(Integer.parseInt(SubscribeTab), GameStatusEnum.GAME_ING);
        this.gameTypeEnum = gameTypeEnum;
        this.SubscribeTab = SubscribeTab;
        GameWorld.ROOM_EXECUTOR_SERVICE.execute(this);
    }


    public void setNextStepClass(Class<? extends IStep> nextStepClass) {
        this.nextStepClass = nextStepClass;
    }

    protected Class<? extends IStep> getFirstStepClass() {
        return Step1Start.class;
    }

    protected Map<Class<? extends IStep>, IStep> initStepMap() {
        Map<Class<? extends IStep>, IStep> stepMap = new HashMap<>();
        stepMap.put(Step1Start.class, new Step1Start());
        stepMap.put(Step2Over.class, new Step2Over());
        return stepMap;
    }

    /**
     * 结算
     */
    public void gameOver() {
        try {
            HallServer.gameLogService.gameOver(SubscribeTab, users);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 终止游戏
     */
    public void terminate() {
        isTerminated = true;
        GameWorld.removeRoom(SubscribeTab);
    }

    @Override
    public void run() {
        log.info("开始游戏，房间:{}", hashCode());
        try {
            nextStepClass = getFirstStepClass();
            do {
                log.debug("room:{},nextStepClass:{}", hashCode(), nextStepClass);
                IStep step = stepMap.get(nextStepClass);
                currStepClass = nextStepClass;
                step.start(this);
            } while (!isTerminated && !Objects.isNull(nextStepClass));
        } catch (Throwable e) {
            log.error("游戏运行异常", e);
        }
        log.info("游戏结束，房间:{}", hashCode());
    }

    public boolean isTerminated() {
        return isTerminated;
    }

    /**
     * 游戏阶段倒计时
     * @param userId
     * @param time
     */
    public void sendStepTime(Integer userId,int time){
        Map<String,Object> stepTime=new HashMap<>();
        stepTime.put("userId",userId);
        stepTime.put("stepTime",time);
        HallServer.publishService.publish(SubscribeTab,userId, MyUtils.putMsg("countDown", stepTime));
    }


    public GameTypeEnum getGameTypeEnum() {
        return gameTypeEnum;
    }
}
